// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <signal.h>
#include <iterator>
#include <memory>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <inference_engine.hpp>
#include<chrono>

using namespace InferenceEngine;

#define tcout                  std::cout
#define file_name_t            std::string
#define imread_t               cv::imread
#define NMS_THRESH 0.45
#define BBOX_CONF_THRESH 0.5
namespace rm
{

static const int INPUT_W = 416;
static const int INPUT_H = 416;
static const int NUM_CLASSES = 4; // COCO has 80 classes. Modify this value on your own dataset.

class Object
{
public:
    cv::Rect_<float> rect;
    int label;
    float prob;
    Object& operator=(const Object& r)
    {
        if (this != &r)
        {
            this->rect = r.rect;
            this->label = r.label;
            this->prob = r.prob;
        }
        return *this;
    }
};

struct GridAndStride
{
    int grid0;
    int grid1;
    int stride;
};

class Yolox
{
public:
    Yolox(){}
    ~Yolox(){}
    //初始化
    bool init();

    //处理图像获取结果
    bool dectect(cv::Mat& frame);
    void draw_objects(cv::Mat _image);
    const std::vector<Object> getObjects();
private:
    cv::Mat static_resize(cv::Mat& img);
    void blobFromImage(cv::Mat& img, Blob::Ptr& blob);
    void generate_grids_and_stride(const int target_w, const int target_h,
                                          std::vector<int>& strides, std::vector<GridAndStride>& grid_strides);
    void generate_yolox_proposals(std::vector<GridAndStride> grid_strides,
                                         const float* feat_ptr, float prob_threshold, std::vector<Object>& objects);
    float intersection_area(const Object& a, const Object& b);
    void qsort_descent_inplace(std::vector<Object>& faceobjects, int left, int right);
    void qsort_descent_inplace(std::vector<Object>& objects);
    void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked, float nms_threshold);
    void decode_outputs(const float* prob, std::vector<Object>& objects, float scale, const int img_w, const int img_h);

    cv::Mat image;
    ExecutableNetwork executable_network;
    DataPtr output_info;
    InferRequest infer_request;
    std::string input_name;
    std::string output_name;
    std::vector<Object> objects;
    const float color_list[4][3] =
    {
        {0.000, 0.447, 0.741},
        {0.850, 0.325, 0.098},
        {0.929, 0.694, 0.125},
        {0.494, 0.184, 0.556}
    };
};
}
